﻿using Google.GData.Client;
using System;
using System.Xml;
using Google.GData.Extensions;

namespace Google.GData.Sites
{

	public class SitesService : MediaService
	{
		public const string GSitesService = "jotspot";
		public const string SITES_NAMESPACE = "http://schemas.google.com/sites/2008";
		public const string KIND_SCHEME = "http://schemas.google.com/g/2005#kind";
		public const string ATTACHMENT_TERM = SITES_NAMESPACE + "#attachment";
		public const string WEBPAGE_TERM = SITES_NAMESPACE + "#webpage";
		public const string FILECABINET_TERM = SITES_NAMESPACE + "#filecabinet";
		public const string PARENT_REL = SITES_NAMESPACE + "#parent";

		public SitesService(string service, string applicationName, string domain, string siteName)
			: base(service, applicationName)
		{
			Domain = domain;
			SiteName = siteName;
		}

		public SitesService(string applicationName, string domain, string siteName) : base(GSitesService, applicationName)
		{
			Domain = domain;
			SiteName = siteName;
		}
		public SitesService(string applicationName) : base(GSitesService, applicationName) {}
		public SitesService(string service, string applicationName)
			: base(service, applicationName)
		{
			
		}

		public string Domain { get; set; }
		public string SiteName { get; set; }

		private String makeFeedUri(String type)
		{
			return String.Format("https://sites.google.com/feeds/{0}/{1}/{2}/", type, Domain, SiteName);
		}
		private String makePageUri (String path) 
		{
			return String.Format("{0}?path={1}",  makeFeedUri("content"), path);
		}

		private XmlExtension makePageNameExtension(String pageName)
		{
			XmlDocument xmlDocument = new XmlDocument();
			XmlNode pageNameNode = xmlDocument.CreateNode(XmlNodeType.Element,
			  "sites", "pageName", SitesService.SITES_NAMESPACE);
			pageNameNode.InnerText = pageName;
			
			return new XmlExtension(pageNameNode);
		}

		public String getCategoryLabel(AtomCategoryCollection categories)
		{
			foreach (AtomCategory cat in categories)
			{
				if (cat.Scheme == SitesService.KIND_SCHEME)
				{
					return cat.Label;
				}
			}
			return null;
		}


		public AtomEntry PageEntry(String path) 
		{
			FeedQuery query = new FeedQuery(makePageUri(path));
			AtomFeed feed = base.Query(query);
			return feed.Entries[0];
		}
		
		public string EditUri(String path) {
			AtomEntry entry = PageEntry(path);
			return entry.EditUri.Content;
		}
		
		public void getContentFeed()
		{
			getContentFeed(makeFeedUri("content"));
		}

		public void getContentFeed(String feedUri)
		{
			FeedQuery query = new FeedQuery(feedUri);
			AtomFeed feed = Query(query);
		}

		public void getContentByType(String type)
		{
			String feedUri = makeFeedUri("content") + String.Format("?kind={2}", type);
			getContentFeed(feedUri);
		}

		// TODO: replace these with more useful options, rather than write-to-console

		//public void getActivityFeed()
		//{
		//    getActivityFeed(makeFeedUri("activity"));
		//}

		//public void getActivityFeed(String feedUri)
		//{
		//    FeedQuery query = new FeedQuery();
		//    query.Uri = new Uri(feedUri);
		//    AtomFeed feed = Query(query);

		//    foreach (AtomEntry entry in feed.Entries)
		//    {
		//        Console.WriteLine(String.Format("Page: {0}", entry.Title.Text));

		//        String actionType = getCategoryLabel(entry.Categories);
		//        Console.WriteLine(String.Format("  {0} on {1}, by {2}", actionType,
		//            entry.Updated.ToShortDateString(), entry.Authors[0].Email));
		//    }
		//}

		//public void getRevisionFeed(String entryId)
		//{
		//    FeedQuery query = new FeedQuery();
		//    String feedUri = makeFeedUri("revision") + entryId;
		//    query.Uri = new Uri(feedUri);
		//    AtomFeed feed = Query(query);


		//    foreach (AtomEntry entry in feed.Entries)
		//    {
		//        XmlExtension revisionNum = (XmlExtension)entry.FindExtension("revision", SitesService.SITES_NAMESPACE);
		//        Console.WriteLine(String.Format("revision id: {0}", revisionNum.Node.InnerText));
		//        Console.WriteLine(String.Format("  html: {0}...", entry.Content.Content.Substring(0, 100)));
		//        Console.WriteLine(String.Format("  site link: {0}", entry.AlternateUri.ToString()));
		//    }
		//}

		public AtomEntry createWebPage(String title, String html, String pageName)
		{
			SiteEntry entry = new SiteEntry();
			AtomCategory category = new AtomCategory(SitesService.WEBPAGE_TERM, SitesService.KIND_SCHEME);
			category.Label = "webpage";
			entry.Categories.Add(category);
			entry.Title.Text = title;
			entry.Content.Type = "xhtml";
			entry.Content.Content = html;
			entry.ExtensionElements.Add(makePageNameExtension(pageName));

			AtomEntry newEntry = null;
			try
			{
				newEntry = Insert(new Uri(makeFeedUri("content")), entry);
			}
			catch (GDataRequestException e)
			{
				Console.WriteLine(e.ResponseString);
			}

			return newEntry;
		}
		
		public AtomEntry updateWebPage(String title, String html, String path)
		{
			AtomEntry entry = PageEntry(path);
			AtomContent y = new AtomContent() {
				Type = "xhtml",
				Content = html
			};

			// update title and content
			if (!String.IsNullOrEmpty(title)) {
				entry.Title.Text = title; 
			}
			entry.Content = y;

			AtomEntry newEntry = null;
			try
			{
				newEntry = Update(entry);
			}
			catch (GDataRequestException e)
			{
				// TODO: replace with error report (or remove t/c)
				Console.WriteLine(e.ResponseString);
			}

			return newEntry;
		}

		public AtomEntry uploadAttachment(String filename, String contentType, AtomEntry parent, String title, String description)
		{
			SiteEntry entry = new SiteEntry();

			AtomCategory category = new AtomCategory(SitesService.ATTACHMENT_TERM, SitesService.KIND_SCHEME);
			category.Label = "attachment";
			entry.Categories.Add(category);

			AtomLink parentLink = new AtomLink(AtomLink.ATOM_TYPE, SitesService.PARENT_REL);
			parentLink.HRef = parent.SelfUri;
			entry.Links.Add(parentLink);

			entry.MediaSource = new MediaFileSource(filename, contentType);
			entry.Content.Type = contentType;

			if (title == "")
			{
				entry.Title.Text = entry.MediaSource.Name;
			}
			else
			{
				entry.Title.Text = title;
			}

			entry.Summary.Text = description;

			AtomEntry newEntry = null;
			try
			{
				newEntry = Insert(new Uri(makeFeedUri("content")), entry);
			}
			catch (GDataRequestException e)
			{
				Console.WriteLine(e.ResponseString);
			}

			return newEntry;
		}

	}

}
